package org.robert.export_client.config.executor;

import lombok.extern.slf4j.Slf4j;

import java.util.Map;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

/**
 * @Description 公用线程池
 * @Author robert
 * @Date 2022/12/25 16:50
 **/
@Slf4j
public class ExportThreadPoolExecutor extends ThreadPoolExecutor {

    // 用于存储每个任务的提交时间和完成时间
    private final Map<Runnable, Long> taskTimestamps = new ConcurrentHashMap<>();
    // 记录已提交但未开始的任务数量
    private final AtomicInteger pendingTasksCount = new AtomicInteger(0);
    // 总计等待时间
    private final AtomicLong waitTimeTotal = new AtomicLong(0);

    // 每一个任务的预计等待时间
    private final Map<Runnable, Long> estimatedExecutionTimes = new ConcurrentHashMap<>();

    // 每一个任务的执行时间
    private final Map<Runnable, Long> taskRunTime = new ConcurrentHashMap<>();


    public ExportThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
    }

    public ExportThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime,
                                    TimeUnit unit, BlockingQueue<Runnable> workQueue,
                                    ThreadFactory threadFactory) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory);
    }

    public ExportThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, handler);
    }

    public ExportThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);
    }

    @Override
    protected void beforeExecute(Thread t, Runnable r) {
        log.info("Task: {}, 开始执行,", Thread.currentThread().getName());
        super.beforeExecute(t, r);
        int i = pendingTasksCount.decrementAndGet();
        log.info("线程池未执行数量：{}", i);
        taskTimestamps.put(r, System.currentTimeMillis());
    }

    @Override
    protected void afterExecute(Runnable r, Throwable t){
        super.afterExecute(r, t);
        if (taskTimestamps.containsKey(r)) {
            long startTime = taskTimestamps.get(r);
            long endTime = System.currentTimeMillis();
            long executionTime = endTime - startTime;
            // 这里可以记录任务的执行时间
            taskTimestamps.remove(r);
            long l = waitTimeTotal.addAndGet(-executionTime);
            taskRunTime.remove(r);
            // 重新设置时间，
            estimatedExecutionTimes.remove(r);
            logExecutionTime(executionTime, r);
            log.info("线程池剩余总数量：{}", getQueue().size());
            log.info("剩余等待总时间：{}", l);
            if(getQueue().size() == 0){
                log.info("waitTimeTotal 重置");
                waitTimeTotal.intValue();
            }
        }
    }

    private void logExecutionTime(long executionTime, Runnable task) {
        // 实现你的日志记录逻辑
        log.info("Task: {} , 总计执行时间: {} ms", Thread.currentThread().getName(), executionTime);
    }

    public Long getTaskWaitTime(Runnable task, long runTime){
        // 根据当前线程池状态和其他算法计算预计执行时间并存储
        taskRunTime.put(task, runTime);
        int i = pendingTasksCount.getAndIncrement();
        log.info("Task:{},当前排队：{}, 需要等待时间: {}", Thread.currentThread().getName(), i, waitTimeTotal);
        long waitTime = waitTimeTotal.addAndGet(runTime);
        log.info("Task:{}，预计执行完成时间: {}", Thread.currentThread().getName(), waitTime);
        estimatedExecutionTimes.put(task, waitTime);
        return waitTime;
    }

}
